
#include "Query.h"


#include "Query.h"


#include "Query.h"


#include "CCardStack.h"


#include "CCardStack.h"


#include "Query.h"


#include "GameState.h"


#include "GameState.h"

#include "strategies/PointBracketingKnockingStrategy.h"

bool PointBracketingKnockingStrategy::decideKnock(CCardStack* hand, const GameState* gameState) {
    bool knock;
    int currentHandValue = hand->Value();
    int opponent = (gameState->getCurrPlayer() + 1) % 2;
    // Initialize bracket from history
    int minOppScore = gameState->minPoints[opponent];
    int maxOppScore = 30;
    // Try to reduce the bracket with the cards to be known in the opponent's hand
    CCardStack oppHand = gameState->getCardsPickedUpAndHeldByPlayer(opponent);
    Query::debugOut(string("Known pponent hand: ") + string(oppHand.Initials()) + "\n", 2);
    int numKnownCards = oppHand.Size();
    if (numKnownCards == 3) {
        knock = (currentHandValue > oppHand.Value());
        decisionCertainty = 100;
        Query::debugOut("All cards are known", 2);
    }
    else {
        int scoringSuit = gameState->scoringSuit[opponent];
        if (scoringSuit != -1) {
            // Have the opponent on a given suit, so fill in min and max cards for that suit
            CCardStack possibleCards = gameState->getUnknownCards(gameState->getCurrPlayer());
            int cardsToFill = 3 - numKnownCards;
            // For minimum score
            while (cardsToFill > 0) {
                CCardStack minCards = Query::minValueCards(possibleCards, (eSuit) scoringSuit);
                oppHand.Push(minCards);
                cardsToFill -= minCards.Size();
                if (cardsToFill < 0) {
                    oppHand.Pop(-cardsToFill);
                }
            }
            int possibleMinScore = oppHand.Value();
            if (possibleMinScore > minOppScore) {
                minOppScore = possibleMinScore;
            }
            // For maximum score
            cardsToFill = 3 - numKnownCards;
            oppHand.Pop(cardsToFill);
            while (cardsToFill > 0) {
                CCardStack maxCards = Query::maxValueCards(possibleCards, (eSuit) scoringSuit);
                oppHand.Push(maxCards);
                cardsToFill -= maxCards.Size();
                if (cardsToFill < 0) {
                    oppHand.Pop(-cardsToFill);
                }
            }
            int possibleMaxScore = oppHand.Value();
            if (possibleMaxScore < maxOppScore) {
                maxOppScore = possibleMaxScore;
            }
        }
        else {
            // For min score
            int partialHandValue = oppHand.Value();
            if (partialHandValue > minOppScore) {
                minOppScore = partialHandValue;
            }
            // For max score
            if (numKnownCards == 2) {
                maxOppScore = partialHandValue + 9; // Subtracting achieved score from maximum possible score with number of cards
            }
            else if (numKnownCards == 1) {
                maxOppScore = partialHandValue + 19;
            }
        }
        // Make decision based on the range and the given bracket percentage
        int decisionPoint = minOppScore + (bracketPct * (maxOppScore - minOppScore)) / 100;
        Query::debugOut("Min score: ", 2);
        Query::debugValue(minOppScore, 2);
        Query::debugOut("Max score: ", 2);
        Query::debugValue(maxOppScore, 2);
        knock = currentHandValue > decisionPoint;
        // Calculate decision certainty
        if (currentHandValue < minOppScore) {
            decisionCertainty = 100;
        }
        else {
            float probOppBetter = (float) (maxOppScore - currentHandValue + 1) / (maxOppScore - minOppScore + 1);
            if (knock) {
                decisionCertainty = (int) (100 * (1.0f - probOppBetter));
            }
            else {
                decisionCertainty = (int) (100 * probOppBetter);
            }
        }
    }
    Query::debugOut("Decision certainty for knocking: ", 2);
    Query::debugValue(decisionCertainty, 2);
    return knock;
}
